#include <stdio.h>
#include <memory.h>
#include <utility>
#include <algorithm>

static short height[100][100]; /* height of each point */
static short length[100][100]; /* longest path from each point */

typedef std::pair<unsigned char, unsigned char> coordinate_t;
static coordinate_t coordinates[10000];

static bool coordinate_comparer(const coordinate_t &x, const coordinate_t &y)
{
    return height[x.first][x.second] < height[y.first][y.second];
}

int solve()
{
    int num_rows, num_cols;
    if (scanf("%d %d", &num_rows, &num_cols) != 2)
        return 0;
    
    int n = num_rows * num_cols, k = 0;
    for (int i = 0; i < num_rows; i++)
        for (int j = 0; j < num_cols; j++)
        {
            scanf("%d", &height[i][j]);
            coordinates[k++] = coordinate_t(i, j);
        }

    std::sort(coordinates + 0, coordinates + n, coordinate_comparer);
    memset(length, 0, sizeof(length));
    short longest = 0;
    for (k = 0; k < n; k++)
    {
        int i = coordinates[k].first, j = coordinates[k].second;
        short h = height[i][j], L = 0;
        if (i > 0 && height[i-1][j] < h)
            L = std::max(L, length[i-1][j]);
        if (i < num_rows - 1 && height[i+1][j] < h)
            L = std::max(L, length[i+1][j]);
        if (j > 0 && height[i][j-1] < h)
            L = std::max(L, length[i][j-1]);
        if (j < num_cols - 1 && height[i][j+1] < h)
            L = std::max(L, length[i][j+1]);
        length[i][j] = L + 1;
        longest = std::max(longest, length[i][j]);
    }
    printf("%d\n", (int)longest);
    return 1;
}

int main()
{
    while (solve());
    return 0;
}